#include "mapmanager.h"
#include "networkmanager.h"
#include <QDebug>
#include <QFile>
#include <QDir>
#include "painters.h"
#include "scenemanager.h"
MapManager* MapManager::manager = nullptr;

void MapManager::paint(QPainter &painter)
{
    if(!ready) return;
    (void) painter;
    if(_image_svg){
//        painter.drawImage(QPointF(0, 0), *_image_svg);
    }

    paintStations(painter);
    paintEdges(painter);

    if(_selectline == 1){
        Painters::targetline(false)(painter);
        paintLine2(painter);
        Painters::targetline(true)(painter);
        paintLine1(painter);
    } else {
        Painters::targetline(false)(painter);
        paintLine1(painter);
        Painters::targetline(true)(painter);
        paintLine2(painter);
    }
}

void MapManager::paintStations(QPainter &painter)
{
    for(auto it = _id_nodes.begin(); it != _id_nodes.end(); ++it){
        Painters::station(it.value()->line)(painter);
        painter.drawEllipse(it.value()->pos, 10, 10);
        QString print("  " + it.value()->name);
        painter.setPen(QPen(painter.pen().color(), 2));
        painter.drawText(it.value()->pos, print);
    }
}

void MapManager::paintEdges(QPainter &painter)
{
    for(const auto& edges : _graph){
        for(const auto& edge : edges){
            if(_id_nodes.count(edge.id1)){
                QPointF src = _id_nodes[edge.id1]->pos;
                if(_id_nodes.count(edge.id2)){
                    QPointF dst = _id_nodes[edge.id2]->pos;
//                    qDebug() << src << dst;
                    QString id = edge.line;
                    Painters::line(id)(painter);
                    painter.drawLine(src, dst);
                } else {
                    qDebug() << "打印边 : id2 " << edge.id2 << "不存在";
                }
            } else {
                qDebug() << "打印边 : id1 " << edge.id1 << "不存在";
            }
        }
    }
}

void MapManager::paintLine1(QPainter &painter)
{
    if(_finded){
        for(int i = 1; i < _path.size(); ++i){
            if(_id_nodes.count(_path[i - 1]) && _id_nodes.count(_path[i])){
                QPointF src = _id_nodes[_path[i - 1]]->pos;
                QPointF dst = _id_nodes[_path[i]]->pos;
                painter.drawLine(src, dst);
            } else {
                qDebug() << _path[i - 1] << "到 : " << _path[i] << "无法打印";
            }
        }
    }
}

void MapManager::paintLine2(QPainter &painter)
{
    if(_finded2){
        for(int i = 1; i < _path2.size(); ++i){
            if(_id_nodes.count(_path2[i - 1]) && _id_nodes.count(_path2[i])){
                QPointF src = _id_nodes[_path2[i - 1]]->pos;
                QPointF dst = _id_nodes[_path2[i]]->pos;
                painter.drawLine(src, dst);
            } else {
                qDebug() << _path2[i - 1] << "到 : " << _path2[i] << "无法打印";
            }
        }
    }
}

MapManager::MapManager()
    : _image_svg(nullptr) // 先让它为空,然后初始化,初始化完了则不为空
{
    load();
    loadSVG();
}

void MapManager::load()
{
    qDebug() << QDir(".").currentPath();
    if(QDir(".").exists("station.csv")){
        qDebug() << "加载缓存文件";
        loadStations("station.csv");
    } else {
        qDebug() << "加载资源文件";
        loadStations(":/source/data/station.csv");
        QFile::copy(":/source/data/station.csv", "station.csv");
        QFile::setPermissions("station.csv", QFileDevice::ReadOwner | QFileDevice::WriteOwner);
    }
    if(QDir(".").exists("edge.csv")){
        loadEdges("edge.csv");
    } else {
        loadEdges(":/source/data/edge.csv");
        QFile::copy(":/source/data/edge.csv", "edge.csv");
        QFile::setPermissions("edge.csv", QFileDevice::ReadOwner | QFileDevice::WriteOwner);
    }
    if(QDir(".").exists("update_station_status.csv")){
        loadClosed("update_station_status.csv");
    } else {
        loadClosed(":/source/data/update_station_status.csv");
        QFile::copy(":/source/data/update_station_status.csv", "update_station_status.csv");
        QFile::setPermissions("update_station_status.csv", QFileDevice::ReadOwner | QFileDevice::WriteOwner);

    }
}

void MapManager::reload()
{
//    loadStations(":/source/data/station.csv");
//    loadEdges(":/source/data/edge.csv");
//    NetworkManager::instance().getPos(&_id_nodes, &ready);
    _graph.clear();
    _lines.clear();
    _id_nodes.clear();
    _name_nodes.clear();
    _erase_node_line.clear();
    _path.clear();
    _path2.clear();
    _finded = false;
    _finded2 = false;
    load();
}

void MapManager::loadStations(const QString& path)
{
    QFile file(path);
    file.open(QIODevice::ReadOnly);
    QStringList lines(QString::fromLocal8Bit(file.readAll()).split('\n'));
    for(const auto& line : lines){
        if(line.isEmpty()) {
            qDebug() << "station表有空行";
            continue;
        }
        qDebug() << "开始解析station表的行 : " << line;
        QStringList parts(line.split(','));
        if(parts.size() < 4) {
            qDebug() << "station表有行的列数少了!!!!!!";
            continue;
        }
        if(parts[0].size())
        {
            QSharedPointer<Node> node = nullptr;
            if(_id_nodes.count(parts[0])){
                qDebug() << "id重复: " << parts[0];
                node = _id_nodes[parts[0]];
            } else {
                node = QSharedPointer<Node>(new Node);
                node->id = parts[0];
            }
            if(parts[1].size()) node->name = parts[1];
            else qDebug() << "station表有节点没有名字";
            if(parts[2].size()){
                QStringList l(parts[2].split('.'));
                l.removeAll("");
                if(l.empty()) qDebug() << "station表有节点没填线路";
                for(const auto& e : l){
                    if(node->line.contains(e)) {
                        qDebug() << node->id << "节点路线重复: " << e;
                    } else{
                        node->line.push_back(e);
                        qDebug() << node->id << "节点添加路线: " << e;
                    }
                }
            } else {
                qDebug() << "station表有节点没有路线";
            }
            if(parts[3].size()){
                QStringList l(parts[3].split('|'));
                l.removeAll("");
                if(l.size() != 2) qDebug() << "station表有节点的坐标没填对";
                else node->pos = {l[0].toFloat(), l[1].toFloat()};
                qDebug() << node->pos;
            }
            if(_name_nodes.count(node->name)) qDebug() << "name重复 : " << node->name;
            _id_nodes[node->id] = node;
            _name_nodes[node->name].push_back(node);
        }
        else qDebug() << "station表有节点没有id";
    }

    file.close();
}

void MapManager::loadEdges(const QString& path)
{
    QFile file(path);
    file.open(QIODevice::ReadOnly);
    QStringList lines(QString::fromLocal8Bit(file.readAll()).split('\n'));
    for(const auto& line : lines){
        if(line.isEmpty()) {
            qDebug() << "edge表有空行";
            continue;
        }
        qDebug() << "开始解析edge表的行 : " << line;
        QStringList parts(line.split(','));
        if(parts.size() != 4) qDebug() << "edge表有行格式错误";
        if(parts.size() < 4) continue;
        if(parts[0].isEmpty() || parts[1].isEmpty() || parts[2].isEmpty()) continue;
        Edge edge(parts[0], parts[1], parts[2], parts[3].toInt());
        if(_graph[parts[1]].contains(edge)) qDebug() << "边重复添加 : " << parts[1];
        else _graph[parts[1]].push_front(edge);
        if(_graph[parts[2]].contains(edge)) qDebug() << "边重复添加 : " << parts[2];
        else _graph[parts[2]].push_front(edge);

        if(!_lines[parts[0]][parts[1]].contains(parts[2])) _lines[parts[0]][parts[1]].push_back(parts[2]);
        if(!_lines[parts[0]][parts[2]].contains(parts[1])) _lines[parts[0]][parts[2]].push_back(parts[1]);

        if(!_id_nodes[parts[1]]->line.contains(parts[0])) _id_nodes[parts[1]]->line.push_back(parts[0]);
        if(!_id_nodes[parts[2]]->line.contains(parts[0])) _id_nodes[parts[2]]->line.push_back(parts[0]);
    }

    file.close();
}

void MapManager::loadClosed(const QString &path)
{
    QFile file(path);
    file.open(QIODevice::ReadOnly);
    QStringList lines(QString::fromLocal8Bit(file.readAll()).split('\n'));
    for(const auto& line : lines){
        if(line.isEmpty()) {
            qDebug() << "update_station_status表有空行";
            continue;
        }
        qDebug() << "开始解析update_station_status表的行 : " << line;
        QStringList parts(line.split(','));
        if(parts.size() != 3) qDebug() << "update_station_status表有行格式错误";
        if(parts.size() < 3) continue;
        if(parts[2].front() == "开") continue;
        if(_name_nodes.count(parts[0])){
            erase(_name_nodes[parts[0]][0]->id, parts[1]);
        }
    }

    file.close();
}

void MapManager::loadSVG()
{
    // qt的SVG模块根本没法用,bug一堆
//    NetworkManager::instance().getSVG(&_image_svg);
    _image_svg = new QImage(":/source/image/map.png");
}

void MapManager::storage()
{
    QFile station("station_new.csv");
    station.open(QIODevice::WriteOnly | QIODevice::NewOnly);
    QTextStream out_s(&station);
    for(const auto& node : _id_nodes){
        QString line = node->id + "," + node->name + ",";
        for(int i = 0; i < node->line.size(); ++i) {
            if(i) line += ".";
            line += node->line[i];
        }
        line += "," + QString::number(node->pos.x()) + "|" + QString::number(node->pos.y()) + "\n";
        out_s << line;
    }
    QFile::setPermissions("station_new.csv", QFileDevice::ReadOwner | QFileDevice::WriteOwner);
    station.close(); // 这里必须显示关闭,不然下面没法改名
    QDir curdir(".");
    qDebug() << "remove : " << curdir.remove("station.csv");
    qDebug() << "rename : " << curdir.rename("station_new.csv", "station.csv");
    QFile::setPermissions("station.csv", QFileDevice::ReadOwner | QFileDevice::WriteOwner);
}

void MapManager::erase(const QString &node_id, const QString &line)
{
    if(_id_nodes.count(node_id) == 0) return;
    if(!_id_nodes[node_id]->line.contains(line)) return;
    QStringList tgtnodes; // 这个就是line边上和node_id直接相邻的点
    if(_lines[line].count(node_id)){
        tgtnodes = _erase_node_line[node_id][line] = _lines[line][node_id];
    }

    if(tgtnodes.empty())return;

    // 消除邻接表中同时包含tgtnodes和node_id的边
    for(auto it = _graph[node_id].begin(); it != _graph[node_id].end();){
        if(tgtnodes.contains(it->id1) || tgtnodes.contains(it->id2)) {
            it = _graph[node_id].erase(it);
        } else{
            ++it;
        }
    }
    for(auto& tgt : tgtnodes){
        for(auto it = _graph[tgt].begin(); it != _graph[tgt].end();){
            if(node_id == it->id1 || node_id == it->id2) {
                it = _graph[tgt].erase(it);
            } else {
                ++it;
            }
        }
    }

    // 消除 _lines 中 _node_id 相关的边
    _lines[line].erase(_lines[line].find(node_id));
    for(auto& tgt : tgtnodes){
        _lines[line][tgt].removeAll(node_id);
    }
    qDebug() << "删除成功?";
}

static QString getsameline(const QStringList &list1, const QStringList &list2) {
    QSet<QString> set1(list1.begin(), list1.end());
    for(const QString &e : list2) if(!e.isEmpty() && set1.contains(e)) return e;
    return "";
}

QStringList MapManager::getPath(int path)
{
    QStringList find;
    const auto& tgt = path == 1 ? _path : _path2;
    int count = tgt.size(), trans = 0;
    QString prev;
    for (auto e = tgt.begin(); e != tgt.end(); ++e) {
        QString line(_id_nodes[*e]->name);
        if (e != tgt.begin()) {
            QString cur = getsameline(_id_nodes[*(e-1)]->line, _id_nodes[*e]->line);
            if(!prev.isEmpty() && prev != cur) trans++;
            prev = cur;
        }
        for (int i = 0; i < _id_nodes[*e]->line.size(); ++i) {
            if(i) line += "," + _id_nodes[*e]->line[i];
            else line += "-" + _id_nodes[*e]->line[i];
        }
        find << line;
    }

    QString add = QString("%1站, %2换乘").arg(count).arg(trans);
    find << add;
    return find;
}

void MapManager::initMap(QWidget* scene)
{
    (void) scene;
}

void MapManager::getSearchData(QStringList &searchData)
{
    for(auto& node : _id_nodes){
        for(auto& line : node->line){
            QString data(node->name + "-" + line + "号线");
            searchData << data;
        }
    }
}

QSharedPointer<Node> MapManager::findNodeAt(const QPointF &worldPos, double radius)
{
    // 这里记得减半径,不然worldPos会变成左上角
    QRectF tgt(QPointF(worldPos.x() - radius, worldPos.y() - radius), QSize(2 * radius, 2 * radius));
    for(auto it = _id_nodes.begin(); it != _id_nodes.end(); ++it){
        if(tgt.contains(it.value()->pos)) {
            qDebug() << "找到站点 : " <<  it.value()->name << " 于 " << it.value()->pos;
            return it.value();
        }
    }
    return nullptr;
}

void MapManager::connect(const QString &src, const QString &dst, const QString& line)
{
    QString l = line;
    if(l.isEmpty()) l = _id_nodes[src]->line[0];
    Edge edge(l, src, dst, 1);
    _graph[src].push_front(edge);
    _graph[dst].push_front(edge);
//    if(!_lines[line][src].contains(dst)) _lines[line][src].push_back(dst);
//    if(!_lines[line][dst].contains(src)) _lines[line][dst].push_back(src);
}

void MapManager::disconnect(const QString &src, const QString &dst)
{
    for(auto it = _graph[src].begin(); it != _graph[src].end(); ++it){
        if(it->id1 == dst || it->id2 == dst){
            _graph[src].erase(it);
            break;
        }
    }
    for(auto it = _graph[dst].begin(); it != _graph[dst].end(); ++it){
        if(it->id1 == src || it->id2 == src){
            _graph[dst].erase(it);
            break;
        }
    }
}

void MapManager::findpath(const QString &src, const QString &dst)
{
    _finded = false;
    _path.clear();
    _findpathThread.init("最少站点", &_id_nodes, &_graph, src, dst, &_path, &_finded, &_lines);
    _findpathThread.start();

    _finded2 = false;
    _path2.clear();
    _findpathThread2.init("最少换乘", &_id_nodes, &_graph, src, dst, &_path2, &_finded2, &_lines, &_transfer);
    _findpathThread2.start();
}

void MapManager::findpathbyname(const QString &src, const QString &src_line, const QString &dst, const QString &dst_line)
{
    QString src_id, dst_id;
    if(_name_nodes.count(src) == 0) {
        return;
    } else {
        for(auto& node : _name_nodes[src]){
            node->line.contains(src_line);
            src_id = node->id;
            break;
        }
    }

    if(_name_nodes.count(dst) == 0){
        return;
    } else {
        for(auto& node : _name_nodes[dst]){
            node->line.contains(dst_line);
            dst_id = node->id;
            break;
        }
    }

    findpath(src_id, dst_id);
}

void MapManager::selectLine(int tgt)
{
    _selectline = tgt;
}
